package com.toonan.core.util;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.List;
import java.util.regex.Pattern;

import org.springframework.data.annotation.Id;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.util.Assert;

import com.google.common.collect.Lists;
import com.toonan.core.constant.WebplusCons;
import com.toonan.core.matatype.Dto;
import com.toonan.core.vo.PageResult;


/**
 * 
 * @ClassName:  WebplusMongo   
 * @Description:MongoDB 辅助工具类
 * @author: 陈骑元（chenqiyuan@toonan.com)
 * @date:   2022年2月12日 下午8:19:48     
 * @Copyright: 2022 www.toonan.com Inc. All rights reserved. 
 * 注意：本内容仅限于广州市图南软件有限公司内部传阅，禁止外泄以及用于其他的商业目
 */
public class WebplusMongo {
	
    
	/**
	 * 
	 * 简要说明：设置id查询条件 
	 * 编写者：陈骑元（chenqiyuan@toonan.com）
	 * 创建时间： 2022年2月17日 下午9:52:21 
	 * @param 说明
	 * @return 说明
	 */
	public static Query setQueryById(Object id) {
		
		Query query=new Query();
		query.addCriteria(Criteria.where("_id").is(id));
		
		return query;
	}
	
	/**
	 * 
	 * 简要说明：设置id查询条件
	 * 编写者：陈骑元（chenqiyuan@toonan.com）
	 * 创建时间： 2022年2月17日 下午9:52:21 
	 * @param 说明
	 * @return 说明
	 */
	public static Query setQueryByBatchId(Collection<? extends Serializable> idList) {
		
		Query query=new Query();
		query.addCriteria(Criteria.where("_id").in(idList));;
		
		return query;
	}
   /**
    * 
    * 简要说明：设置id查询
    * 编写者：陈骑元（chenqiyuan@toonan.com）
    * 创建时间： 2022年2月16日 下午11:55:39 
    * @param 说明
    * @return 说明
    */
	public static void   eqById(Query query,String id) {
		
		query.addCriteria(Criteria.where("_id").is(id));
	}
	/**
	 * 
	 * 简要说明：左匹配模糊查询
	 * 编写者：陈骑元（chenqiyuan@toonan.com）
	 * 创建时间： 2022年2月12日 下午8:45:43 
	 * @param 说明
	 * @return 说明
	 */
	public static void llike(Query query,String key,Dto pDto) {
		String value=pDto.getString(key);
		leftLike(query,key,value);
	}
	/**
	 * 
	 * 简要说明：左模糊匹配
	 * 编写者：陈骑元（chenqiyuan@toonan.com）
	 * 创建时间： 2022年2月12日 下午8:45:43 
	 * @param 说明
	 * @return 说明
	 */
	public static void leftLike(Query query,String key,String value) {
		if(WebplusUtil.isNotAnyEmpty(key,value)) {
			Pattern pattern = Pattern.compile("^"+value+".*$", Pattern.CASE_INSENSITIVE);
			query.addCriteria(Criteria.where(key).regex(pattern));
		}
	}
	
	/**
	 * 
	 * 简要说明：右匹配模糊查询
	 * 编写者：陈骑元（chenqiyuan@toonan.com）
	 * 创建时间： 2022年2月12日 下午8:45:43 
	 * @param 说明
	 * @return 说明
	 */
	public static void rightLike(Query query,String key,Dto pDto) {
		String value=pDto.getString(key);
		rightLike(query,key,value);
	}
	/**
	 * 
	 * 简要说明：右匹配模糊查询
	 * 编写者：陈骑元（chenqiyuan@toonan.com）
	 * 创建时间： 2022年2月12日 下午8:45:43 
	 * @param 说明
	 * @return 说明
	 */
	public static void rightLike(Query query,String key,String value) {
		if(WebplusUtil.isNotAnyEmpty(key,value)) {
			Pattern pattern = Pattern.compile("^.*"+value+"$", Pattern.CASE_INSENSITIVE);
			query.addCriteria(Criteria.where(key).regex(pattern));
		}
	}
	/**
	 * 
	 * 简要说明：右模糊查询
	 * 编写者：陈骑元（chenqiyuan@toonan.com）
	 * 创建时间： 2022年2月12日 下午8:45:43 
	 * @param 说明
	 * @return 说明
	 */
	public static void like(Query query,String key,Dto pDto) {
		String value=pDto.getString(key);
		like(query,key,value);
	}
	/**
	 * 
	 * 简要说明：全模糊查询
	 * 编写者：陈骑元（chenqiyuan@toonan.com）
	 * 创建时间： 2022年2月12日 下午8:45:43 
	 * @param 说明
	 * @return 说明
	 */
	public static void like(Query query,String key,String value) {
		if(WebplusUtil.isNotAnyEmpty(key,value)) {
			Pattern pattern = Pattern.compile("^.*"+value+".*$", Pattern.CASE_INSENSITIVE);
			query.addCriteria(Criteria.where(key).regex(pattern));
		}
	}
	/**
	 * 
	 * 简要说明：添加等于查询条件
	 * 编写者：陈骑元（chenqiyuan@toonan.com）
	 * 创建时间： 2022年2月12日 下午8:22:32 
	 * @param 说明 Query 查询对象  key 查询健，查询值
	 * @return 说明
	 */
	public static void eq(Query query,String key,String value ) {
		if(WebplusUtil.isNotAnyEmpty(key,value)){
			query.addCriteria(Criteria.where(key).is(value));
		}
	}
	
	/**
	 * 
	 * 简要说明：添加等于查询条件
	 * 编写者：陈骑元（chenqiyuan@toonan.com）
	 * 创建时间： 2022年2月12日 下午8:22:32 
	 * @param 说明 Query 查询对象  key 查询健，查询值
	 * @return 说明
	 */
	public static Query eq(String key,String value ) {
		Query query=new Query();
	    query.addCriteria(Criteria.where(key).is(value));
		return query;
	}
    
	/**
	 * 
	 * 简要说明：添加等于查询条件
	 * 编写者：陈骑元（chenqiyuan@toonan.com）
	 * 创建时间： 2022年2月12日 下午8:22:32 
	 * @param 说明 Query 查询对象  key 查询健，pDto 对象集合
	 * @return 说明
	 */
	public static void eq(Query query,String key,Dto pDto ) {
		String value=pDto.getString(key);
		eq(query,key,value );
	}
	/**
	 * 
	 * 简要说明：添加小于查询条件
	 * 编写者：陈骑元（chenqiyuan@toonan.com）
	 * 创建时间： 2022年2月12日 下午8:22:32 
	 * @param 说明 Query 查询对象  key 查询健，查询值
	 * @return 说明
	 */
	public static Query lt(String key,String value ) {
		Query query=new Query();
	    query.addCriteria(Criteria.where(key).lt(value));
		return query;
	}
	/**
	 * 
	 * 简要说明：添加等于查询条件
	 * 编写者：陈骑元（chenqiyuan@toonan.com）
	 * 创建时间： 2022年2月12日 下午8:22:32 
	 * @param 说明 Query 查询对象  key 查询健，查询值
	 * @return 说明
	 */
	public static void lt(Query query,String key,String value ) {
		if(WebplusUtil.isNotAnyEmpty(key,value)){
			query.addCriteria(Criteria.where(key).lt(value));
		}
	}
	/**
	 * 
	 * 简要说明：添加小于查询条件
	 * 编写者：陈骑元（chenqiyuan@toonan.com）
	 * 创建时间： 2022年2月12日 下午8:22:32 
	 * @param 说明 Query 查询对象  key 查询健，pDto 对象集合
	 * @return 说明
	 */
	public static void lt(Query query,String key,Dto pDto ) {
		String value=pDto.getString(key);
		lt(query,key,value );
	}
	
	/**
	 * 
	 * 简要说明：添加大于等于查询条件
	 * 编写者：陈骑元（chenqiyuan@toonan.com）
	 * 创建时间： 2022年2月12日 下午8:22:32 
	 * @param 说明 Query 查询对象  key 查询健，查询值
	 * @return 说明
	 */
	public static void gte(Query query,String key,String value ) {
		if(WebplusUtil.isNotAnyEmpty(key,value)){
			query.addCriteria(Criteria.where(key).gte(value));
		}
	}
	/**
	 * 
	 * 简要说明：添加小于查询条件
	 * 编写者：陈骑元（chenqiyuan@toonan.com）
	 * 创建时间： 2022年2月12日 下午8:22:32 
	 * @param 说明 Query 查询对象  key 查询健，pDto 对象集合
	 * @return 说明
	 */
	public static void gte(Query query,String key,Dto pDto ) {
		String value=pDto.getString(key);
		gte(query,key,value );
	}
	
	/**
	 * 
	 * 简要说明：查询小于日期
	 * 编写者：陈骑元（chenqiyuan@toonan.com）
	 * 创建时间： 2022年3月5日 下午10:11:58 
	 * @param 说明
	 * @return 说明
	 */
	public static void ltDate(Query query,String key,Dto pDto) {
		String value=pDto.getString(key);
		if(WebplusUtil.isNotEmpty(value)) {
			value=WebplusUtil.plusDay(1, value);
			query.addCriteria(Criteria.where(key).lt(value));
		}
	}
	
	/**
	 * 
	 * 简要说明：in条件
	 * 编写者：陈骑元（chenqiyuan@toonan.com）
	 * 创建时间： 2022年2月12日 下午8:22:32 
	 * @param 说明 Query 查询对象  key 查询健，查询值
	 * @return 说明
	 */
	public static void in(Query query,String key,  String value ) {
		List<String> strList=WebplusFormater.separatStringToList(value);
		in(query,key,strList);
	}
	/**
	 * 
	 * 简要说明：in条件
	 * 编写者：陈骑元（chenqiyuan@toonan.com）
	 * 创建时间： 2022年2月12日 下午8:22:32 
	 * @param 说明 Query 查询对象  key 查询健，查询值
	 * @return 说明
	 */
	public static void in(Query query,String key,Dto pDto) {
		String value=pDto.getString(key);
		in(query,key,value);
	}
	/**
	 * 
	 * 简要说明：in条件
	 * 编写者：陈骑元（chenqiyuan@toonan.com）
	 * 创建时间： 2022年2月12日 下午8:22:32 
	 * @param 说明 Query 查询对象  key 查询健，查询值
	 * @return 说明
	 */
	public static void in(Query query,String key,List<String> strList ) {
		if(WebplusUtil.isNotAnyEmpty(key,strList)){
			query.addCriteria(Criteria.where(key).in(strList));
		}
	}
	
	/**
	 * 
	 * 简要说明：nin条件
	 * 编写者：陈骑元（chenqiyuan@toonan.com）
	 * 创建时间： 2022年2月12日 下午8:22:32 
	 * @param 说明 Query 查询对象  key 查询健，查询值
	 * @return 说明
	 */
	public static void nin(Query query,String key,List<String> strList ) {
		if(WebplusUtil.isNotAnyEmpty(key,strList)){
			query.addCriteria(Criteria.where(key).nin(strList));
		}
	}
	/**
	 * 
	 * 简要说明：设置分页
	 * 编写者：陈骑元（chenqiyuan@toonan.com）
	 * 创建时间： 2022年2月15日 下午10:32:05 
	 * @param 说明
	 * @return 说明
	 */
	public static void withPage(Query query,PageResult pageResult) {
		 withPage(query,pageResult.getCurrentPage(),pageResult.getPageSize());
	}
	/**
	 * 
	 * 简要说明：从Dto对象设置分页
	 * 编写者：陈骑元（chenqiyuan@toonan.com）
	 * 创建时间： 2022年2月15日 下午9:48:44 
	 * @param 说明 query查询条件 pDto 值或传输对象
	 * @return 说明 
	 */
	public static void withPage(Query query,Dto pDto) {
		Integer currentPage=Integer.parseInt(pDto.getOrDefault(WebplusCons.PAGE, WebplusCons.DEFAULT_CURRENTPAGE).toString());
		Integer pageSize=Integer.parseInt(pDto.getOrDefault(WebplusCons.LIMIT, WebplusCons.DEFAULT_PAGESIZE).toString());
	    withPage(query,currentPage,pageSize);
	}
	/**
	 * 
	 * 简要说明:设置分页 条件
	 * 编写者：陈骑元（chenqiyuan@toonan.com）
	 * 创建时间： 2022年2月13日 上午11:16:44 
	 * @param 说明   query 查询条件 currentPage 当前页 pageSize 每页数量
	 * @return 说明
	 */
	public static void withPage(Query query,Integer  currentPage,Integer pageSize) {
		if(WebplusUtil.isEmpty(currentPage)||currentPage<0) {
			currentPage=1;
		}
		if(WebplusUtil.isEmpty(pageSize)||pageSize<0) {
			pageSize=20;
		}
		Pageable pageable=PageRequest.of(currentPage - 1,pageSize);
		
		withPage(query,pageable);
	}
	/**
	 * 
	 * 简要说明：设置分页
	 * 编写者：陈骑元（chenqiyuan@toonan.com）
	 * 创建时间： 2022年2月13日 上午11:13:53 
	 * @param 说明
	 * @return 说明
	 */
	public static void  withPage(Query query,Pageable pageable) {
		
		query.with(pageable);
	}
	
	/**
	 * 
	 * 简要说明：原生设置分页
	 * 编写者：陈骑元（chenqiyuan@toonan.com）
	 * 创建时间： 2022年2月15日 下午9:55:55 
	 * @param 说明
	 * @return 说明
	 */
	public static void withNativePage(Query query,Dto pDto) {
		Integer currentPage=Integer.parseInt(pDto.getOrDefault(WebplusCons.PAGE, WebplusCons.DEFAULT_CURRENTPAGE).toString());
		Integer pageSize=Integer.parseInt(pDto.getOrDefault(WebplusCons.LIMIT, WebplusCons.DEFAULT_PAGESIZE).toString());
		withNativePage(query,currentPage,pageSize);
	}
	/**
	 * 
	 * 简要说明：设置分页
	 * 编写者：陈骑元（chenqiyuan@toonan.com）
	 * 创建时间： 2022年2月15日 下午10:34:09 
	 * @param 说明
	 * @return 说明
	 */
	public static void withNativePage(Query query,PageResult pageResult) {
		
		withNativePage(query,pageResult.getCurrentPage(),pageResult.getPageSize());
	}
	/**
	 * 
	 * 简要说明：原生设置分页
	 * 编写者：陈骑元（chenqiyuan@toonan.com）
	 * 创建时间： 2022年2月15日 下午9:54:07 
	 * @param 说明  
	 * @return 说明
	 */
	public static void withNativePage(Query query,Integer  currentPage,Integer pageSize) {
		if(WebplusUtil.isEmpty(currentPage)||currentPage<0) {
			currentPage=1;
		}
		if(WebplusUtil.isEmpty(pageSize)||pageSize<0) {
			pageSize=20;
		}
		long skip=(currentPage-1)*pageSize;
		query.skip(skip).limit(pageSize);
	}
	
	/**
	 * 
	 * 简要说明：升序排序
	 * 编写者：陈骑元（chenqiyuan@toonan.com）
	 * 创建时间： 2022年2月15日 下午10:00:19 
	 * @param 说明 sortField
	 * @return 说明
	 */
	public static void withSortAsc(Query  query,String sortField) {
		if(WebplusUtil.isNotEmpty(sortField)) {
			query.with(Sort.by(Sort.Order.asc(sortField)));
		}
		
	}

	/**
	 * 
	 * 简要说明：升序排序
	 * 编写者：陈骑元（chenqiyuan@toonan.com）
	 * 创建时间： 2022年2月15日 下午10:00:19 
	 * @param 说明 sortField
	 * @return 说明
	 */
	public static void withSortDesc(Query  query,String sortField) {
		if(WebplusUtil.isNotEmpty(sortField)) {
			query.with(Sort.by(Sort.Order.desc(sortField)));
		}
		
	}
	
	/**
	 * 
	 * 简要说明：获取map更新值
	 * 编写者：陈骑元（chenqiyuan@toonan.com）
	 * 创建时间： 2022年2月18日 下午10:27:02 
	 * @param 说明
	 * @return 说明
	 */
	public static Update getUpdateByDto(Dto updateDto) {
		 Update update = new Update();
		 for(String key:updateDto.keySet()) {
			 update.set(key, updateDto.get(key));
		 }
		 return update;
	}
	/**
	 * 
	 * 简要说明：
	 * 编写者：陈骑元（chenqiyuan@toonan.com）
	 * 创建时间： 2022年2月17日 下午10:14:24 
	 * @param 说明
	 * @return 说明
	 */
    public static  Update getUpdateByObject(Object object) {
        Update update = new Update();
        List<String> filedNameList = getFiledName(object);
        for (String filedName:filedNameList) {
            Object filedValue =getFieldValueByName(filedName, object);
            if (filedValue != null) {
                update.set(filedName, filedValue);
            }
        }
        return update;
    }

    /**
     * 
     * 简要说明：获取属性返回的数组
     * 编写者：陈骑元（chenqiyuan@toonan.com）
     * 创建时间： 2022年2月17日 下午10:15:18 
     * @param 说明
     * @return 说明
     */
   public  static List<String> getFiledName(Object o) {
        Field[] fields = o.getClass().getDeclaredFields();
        List<String> fieldNameList=Lists.newArrayList();

        for (Field field:fields) {
           fieldNameList.add(field.getName());
        }

        return fieldNameList;
    }
   /**
    * 
    * 简要说明：获取id的字段
    * 编写者：陈骑元（chenqiyuan@toonan.com）
    * 创建时间： 2022年2月17日 下午10:15:18 
    * @param 说明
    * @return 说明
    */
  public  static String  getIdField(Object o) {
       Field[] fields = o.getClass().getDeclaredFields();
       
          
       for (Field field:fields) {
    	   if (field.isAnnotationPresent(Id.class)) {
    		   
    		   return field.getName();
    	   }
       }

       return "";
   }
    /***
     * 根据属性获取对象属性值
     * @param fieldName
     * @param o
     * @return
     */
    public static Object getFieldValueByName(String fieldName, Object o) {
        try {
            String e = fieldName.substring(0, 1).toUpperCase();
            String getter = "get" + e + fieldName.substring(1);
            Method method = o.getClass().getMethod(getter, new Class[0]);
            return method.invoke(o, new Object[0]);
        } catch (Exception var6) {
            return null;
        }
    }
   /**
    * 
    * 简要说明：获取id值
    * 编写者：陈骑元（chenqiyuan@toonan.com）
    * 创建时间： 2022年2月18日 下午9:47:51 
    * @param 说明
    * @return 说明
    */
   public static Object getIdFieldValue(Object o) {
	   String id=getIdField(o);
	   Assert.notNull(id, "Mongo文档实体没有配置ID配置");
	   
	   return getFieldValueByName(id,o);
   }
	
   
  
}
